package widget.bar;

import android.content.Context;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;

import library.utils.DisplayUtil;


/**
 * Created by Mr.Fan on 2016/11/11.
 */

public class StatusBar extends Bar<StatusBar> {

    private boolean shadow = false;

    public StatusBar(@Nullable SystemBar systemBar) {
        super(systemBar);
    }

    public NavigationBar navigationBar() {
        return getSystemBar().navigationBar();
    }

    public StatusBar shadow(boolean shadow) {
        this.shadow = shadow;
        return this;
    }

    public boolean isShadow() {
        return shadow;
    }

    protected void commit(Window window) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            setStatusBar(window, this);
        }
    }

    /**
     * 4.4之后开始支持透明状态栏
     * 当你把窗口flag设置成 FLAG_TRANSLUCENT_STATUS后，你的应用所占的屏幕扩大到全屏
     * 但是最顶上会有背景透明的状态栏，它的文字可能会盖着你的应用的标题栏
     *
     * @param window
     * @param bar
     */
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    private void setStatusBar(@NonNull Window window, @NonNull StatusBar bar) {
        if (window == null || bar == null)
            return;
        /*
         * 打开状态栏透明效果
         */
        if (bar.isSupport()) {
            FlagCompat.setLayoutStable(window, true);
            FlagCompat.setLayoutFullScreen(window, true);
            FlagCompat.setTranslucentStatus(window, true);
            FlagCompat.setDrawsSystemBarBackground(window, true);
            addStatusView(window, bar);
        } else {
            FlagCompat.setTranslucentStatus(window, false);

            clearStatusBarView(window);
            setStatusBarShadow(window, false);
            if (clearFitDrawable(window)) {
                FlagCompat.setLayoutFullScreen(window, false);
            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                window.setStatusBarColor(Color.BLACK);
//                window.addFlags(STATUS_FLAG);
            }
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    private void clearStatusBarView(@NonNull Window window) {
        final ViewGroup android_content = (ViewGroup) window.findViewById(Window.ID_ANDROID_CONTENT);
        StatusView statusView = getView(android_content, StatusView.class);
        if (statusView != null) {
            android_content.removeView(statusView);
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    private boolean clearFitDrawable(Window window) {
        View contentView = getSystemBar().getContentView();
        if (contentView != null) {
            return clearStatusFitDrawable(contentView, 0);
        } else {
            final ViewGroup android_content = (ViewGroup) window.findViewById(Window.ID_ANDROID_CONTENT);
            return clearStatusFitDrawable(android_content, 2);
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    private void addStatusView(@NonNull Window window, @NonNull StatusBar bar) {
        /*
         * 处理颜色，透明度
         * 在 (id=Window.ID_ANDROID_CONTENT)view 中添加新的status view
         */
        View contentView = getSystemBar().getContentView();
        if (contentView != null) {
            clearStatusBarView(window);
        } else {
            clearFitDrawable(window);
        }
        if (bar.isTransparent()) {
//            D("bar.isTransparent()");
        } else if (bar.isTranslucent()) {
//            D("bar.isTranslucent()");
            setStatusBarColor(window, getSystemBar().getMainColor(), 0xFF / 3);
        } else if (contentView == null) {
//            D("single view");
            setStatusBarColor(window, bar.getColor(), bar.getAlpha());
        } else {// 处理多view
//            D("multi view");
            final int statusBarHeight = DisplayUtil.getStatusBarHeight();
            FitDrawable fitDrawable = getFitDrawable(contentView.getBackground(), bar.getColor(), bar.getAlpha());
            fitDrawable.setLayerInsetTop(1, statusBarHeight);
            contentView.setBackground(fitDrawable);
            setMultiLayoutStatusViewPadding(contentView, statusBarHeight, true);
        }
        /*
         * 添加阴影
         */
        setStatusBarShadow(window, bar.isShadow());
    }

    protected final FitDrawable getFitDrawable(Drawable background, final Integer color, final Integer alpha) {
        FitDrawable origin = null;
        BarDrawable barDrawable = null;
        if (background == null) {
            background = new ColorDrawable(Color.BLACK);
        } else if (background instanceof FitDrawable) {
            origin = (FitDrawable) background;
            Drawable d0 = origin.getDrawable(0);
            background = origin.getDrawable(1);
            if (d0 instanceof BarDrawable)
                barDrawable = (BarDrawable) d0;
        }
        if (barDrawable == null)
            barDrawable = new BarDrawable();
        int c = alphaColor(color, alpha);
        barDrawable.setTopColor(c);
        Drawable[] drawables = new Drawable[]{barDrawable.getDrawable(), background};
        FitDrawable fitDrawable = new FitDrawable(drawables);
        if (origin != null)
            fitDrawable.setLayerInset(1, 0, origin.getLayerInsetTop(), 0, origin.getLayerInsetBottom());
        return fitDrawable;
    }

    /**
     * @param view
     * @param depth view 向内遍历最大层次数
     * @return
     */
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    private boolean clearStatusFitDrawable(View view, int depth) {
        if (view == null || depth <= 0)
            return false;
        Drawable origin = view.getBackground();
        if (origin instanceof FitDrawable) {
            FitDrawable fitDrawable = (FitDrawable) origin;
            fitDrawable.setLayerInsetTop(1, 0);
            setMultiLayoutStatusViewPadding(view, fitDrawable.getLayerInsetTop(), false);
            return true;
        } else if (view instanceof ViewGroup) {
            ViewGroup viewGroup = (ViewGroup) view;
            int count = viewGroup.getChildCount();
            for (int i = count - 1; i >= 0; i--) {
                View v = viewGroup.getChildAt(i);
                if (clearStatusFitDrawable(v, depth--)) {
                    return true;
                }
            }
        }
        return false;
    }


    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    private void setMultiLayoutStatusViewPadding(View contentView, int statusBarHeight, boolean show) {
        final ViewGroup container = (ViewGroup) contentView.getParent();
        if (container == null) {
            return;
        }
        View v = contentView;
        if (show) {
            if (v.getFitsSystemWindows())
                return;
            v.setPadding(
                    v.getPaddingLeft(),
                    v.getPaddingTop() + statusBarHeight,
                    v.getPaddingRight(),
                    v.getPaddingBottom());
        } else {
            v.setPadding(
                    v.getPaddingLeft(),
                    v.getPaddingTop() - statusBarHeight,
                    v.getPaddingRight(),
                    v.getPaddingBottom());
        }
    }

    private void setStatusBarColor(Window window, Integer color, Integer alpha) {
        final ViewGroup android_content = (ViewGroup) window.findViewById(Window.ID_ANDROID_CONTENT);
        StatusView statusView = getView(android_content, StatusView.class);
        int calculateColor = alphaColor(color, alpha);
        if (statusView != null) {
            statusView.setBackgroundColor(calculateColor);
//            D("statusView.setBackgroundColor(0x%X)",calculateColor);
        } else {
            statusView = createStatusBarView(window, calculateColor);
            android_content.addView(statusView);
//            D("createStatusBarView(window, 0x%X)",calculateColor);
        }
    }

    private void setStatusBarShadow(Window window, boolean shadow) {
        final ViewGroup decorView = (ViewGroup) window.getDecorView();
        ShadowView shadowView = getView(decorView, ShadowView.class);
        if (shadow) {
            Drawable d = getGradientDrawable(0xFF / 2);
            if (shadowView != null) {
                shadowView.setBackgroundDrawable(d);
            } else {
                ShadowView statusBarView = createStatusBarView(window, d);
                decorView.addView(statusBarView);
            }
        } else if (shadowView != null)
            decorView.removeView(shadowView);
    }

    private ShadowView createStatusBarView(Window window, Drawable drawable) {
        // 绘制一个和状态栏一样高的矩形
        Context context = window.getContext();
        ShadowView statusBarView = new ShadowView(context);
        ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                DisplayUtil.getStatusBarHeight());
        statusBarView.setLayoutParams(params);
        statusBarView.setBackgroundDrawable(drawable);
        return statusBarView;
    }

    private StatusView createStatusBarView(Window window, int color) {
        // 绘制一个和状态栏一样高的矩形
        Context context = window.getContext();
        StatusView statusBarView = new StatusView(context);
        int height = DisplayUtil.getStatusBarHeight();
        ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, Math.max(0, height));
        statusBarView.setLayoutParams(params);
        statusBarView.setBackgroundColor(color);
        return statusBarView;
    }

    private Drawable getGradientDrawable(int deep) {
        final int split = 10;
        final int[] colors = new int[split + 1];
        final int diff = deep / (split);
        for (int i = 0; i < split; i++) {
            colors[i] = Color.argb(deep - diff * i, 0, 0, 0);
        }
        colors[split] = Color.TRANSPARENT;
        return new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, colors);
    }


    /*
     * ******************************************************************************************
     * Inner Class 仅用于类型判断以避免重复添加view
     * ******************************************************************************************
     */

    private static final class StatusView extends BarView {
        public StatusView(Context context) {
            super(context);
        }
    }

    private static final class ShadowView extends View {

        public ShadowView(Context context) {
            super(context);
            setLayerType(View.LAYER_TYPE_SOFTWARE, new Paint());
        }
    }
}
